library hud;

import 'dart:async';

import 'package:flutter/material.dart';
import 'config.dart';
import 'overlay.dart';
import 'hud.dart';
import 'views/loadding.dart';

export 'views/toast.dart';
export 'views/container.dart';

class Hud {
  static final Hud instance = Hud._interval();
  factory Hud() => instance;

  Hud._interval() {
    config = HudConfig()..init();
  }

  late HudConfig config;

  Widget? _w;
  Widget? get w => _w;
  OverlayEntry? oe;
  BuildContext? ctx;
  Timer? _timer;

  GlobalKey<HudContentState>? _key;
  GlobalKey<HudContentState>? get key => _key;

  static bool get isShow => instance.w != null;
  bool userInteractions = true;

  static Widget init(BuildContext ctx, Widget? child) {
    instance.ctx = ctx;
    return HudView(
      child: child,
    );
  }

  static Future<void> toast(
    String msg, {
    Duration duration = const Duration(milliseconds: 1500),
    HudPosition position = HudPosition.middle,
  }) async {
    if (msg.isEmpty) {
      return;
    }
    instance._show(msg, duration: duration, position: position);
  }

  static Future<void> show({
    HudPosition position = HudPosition.middle,
    HudIndicatorType? indicatorType,
  }) async {
    instance._show(
      '',
      indicator: LoadingIndicator(
        indicatorType: indicatorType,
      ),
      position: position,
    );
  }

  static Future<void> success(
    String msg, {
    Duration duration = const Duration(milliseconds: 1500),
    HudPosition position = HudPosition.middle,
  }) async {
    instance._show(msg,
        indicator: Icon(
          Icons.done,
          color: Hud().config.indicatorColor,
          size: Hud().config.indicatorSize,
        ),
        duration: duration,
        position: position);
  }

  static Future<void> error(
    String msg, {
    Duration duration = const Duration(milliseconds: 1500),
    HudPosition position = HudPosition.middle,
  }) async {
    instance._show(msg,
        indicator: Icon(
          Icons.clear,
          color: Hud().config.indicatorColor,
          size: Hud().config.indicatorSize,
        ),
        duration: duration,
        position: position);
  }

  static Future<void> dismiss() async {
    await instance._dismiss();
  }

  Future<void> _show(
    String msg, {
    Widget? indicator,
    Duration? duration,
    required HudPosition position,
  }) async {
    if (oe == null) return;

    if (_key != null) {
      if (msg.isEmpty) {
        return;
      }
    }

    if (isShow) {
      _cancelTimer();
      await dismiss();
    }

    Completer<void> completer = Completer<void>();
    Completer<void> dismisser = Completer<void>();
    _key = GlobalKey<HudContentState>();
    _w = HudContent(
      key: _key,
      text: msg,
      indicator: indicator,
      position: position,
      completer: completer,
      dismisser: dismisser,
    );
    completer.future.whenComplete(() {
      _cancelTimer();
      _timer = Timer(duration ?? Duration(seconds: Hud.instance.config.timeOut),
          () async {
        await _dismiss(force: true);
      });
    });
    _markNeedsBuild();
    return completer.future;
  }

  Future<void> _dismiss({bool force = false}) async {
    if (!force) {
      if (_key?.currentState?.widget.text.isNotEmpty == true) {
        return;
      }
    }

    _reset();
  }

  void _markNeedsBuild() {
    oe?.markNeedsBuild();
  }

  void _cancelTimer() {
    _timer?.cancel();
    _timer = null;
  }

  void _reset() {
    _w = null;
    _key = null;
    _cancelTimer();
    _markNeedsBuild();
  }
}

class _HudModel {
  final String msg;
  final Widget? indicator;
  final Duration? duration;
  final HudPosition position;

  _HudModel({
    required this.msg,
    required this.position,
    this.indicator,
    this.duration,
  });
}
